use std::io::{self, Write};
use anyhow::Result;
use crate::ftp_client::FtpClient;

/// 交互式FTP客户端界面
pub struct InteractiveInterface {
    client: FtpClient,
    current_directory: String,
    show_help: bool,
    command_history: Vec<String>,
    history_index: usize,
}

impl InteractiveInterface {
    pub fn new(client: FtpClient) -> Self {
        Self {
            client,
            current_directory: "/".to_string(),
            show_help: true,
            command_history: Vec::new(),
            history_index: 0,
        }
    }

    pub async fn run(&mut self) -> Result<()> {
        println!("🚀 FTP Client Interactive Mode");
        println!("===============================");
        
        if self.show_help {
            self.show_help();
        }

        loop {
            let input = self.get_user_input().await?;
            
            if input.trim().is_empty() {
                continue;
            }

            // 添加到历史记录
            self.command_history.push(input.clone());
            self.history_index = self.command_history.len();

            let parts: Vec<&str> = input.trim().split_whitespace().collect();
            if parts.is_empty() {
                continue;
            }

            let command = parts[0].to_lowercase();
            let args = &parts[1..];

            match command.as_str() {
                "help" | "?" => self.show_help(),
                "quit" | "exit" | "bye" => {
                    println!("👋 Goodbye!");
                    break;
                }
                "pwd" => self.handle_pwd().await?,
                "ls" | "dir" | "list" => self.handle_list(args).await?,
                "cd" => self.handle_cd(args).await?,
                "mkdir" | "md" => self.handle_mkdir(args).await?,
                "rmdir" | "rd" => self.handle_rmdir(args).await?,
                "delete" | "del" => self.handle_delete(args).await?,
                "get" | "download" => self.handle_download(args).await?,
                "put" | "upload" => self.handle_upload(args).await?,
                "pasv" => self.handle_pasv().await?,
                "port" => self.handle_port(args).await?,
                "type" => self.handle_type(args).await?,
                "binary" => self.handle_binary().await?,
                "ascii" => self.handle_ascii().await?,
                "rest" => self.handle_rest(args).await?,
                "size" => self.handle_size(args).await?,
                "mdtm" => self.handle_mdtm(args).await?,
                "status" => self.handle_status().await?,
                "history" => self.show_history(),
                "clear" => self.clear_screen(),
                "connect" => self.handle_connect(args).await?,
                "login" => self.handle_login(args).await?,
                "disconnect" => self.handle_disconnect().await?,
                _ => {
                    println!("❌ Unknown command: {}", command);
                    println!("Type 'help' for available commands.");
                }
            }
        }

        Ok(())
    }

    async fn get_user_input(&self) -> Result<String> {
        print!("ftp> ");
        io::stdout().flush()?;
        
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        Ok(input)
    }

    fn show_help(&self) {
        println!("\n📖 Available Commands:");
        println!("=====================");
        println!("Connection:");
        println!("  connect <host> [port]  - Connect to FTP server");
        println!("  login <user> <pass>    - Login to server");
        println!("  disconnect            - Disconnect from server");
        println!("  quit/exit/bye         - Exit client");
        println!();
        println!("Directory Operations:");
        println!("  pwd                   - Print working directory");
        println!("  ls [path]             - List directory contents");
        println!("  cd <path>             - Change directory");
        println!("  mkdir <path>          - Create directory");
        println!("  rmdir <path>          - Remove directory");
        println!();
        println!("File Operations:");
        println!("  get <file> [local]    - Download file");
        println!("  put <file> [remote]   - Upload file");
        println!("  delete <file>         - Delete file");
        println!("  size <file>           - Get file size");
        println!("  mdtm <file>           - Get file modification time");
        println!();
        println!("Transfer Settings:");
        println!("  pasv                  - Set passive mode");
        println!("  port <port>           - Set active mode port");
        println!("  type <A|I>            - Set transfer type");
        println!("  binary                - Set binary transfer");
        println!("  ascii                 - Set ASCII transfer");
        println!("  rest <offset>         - Set resume offset");
        println!();
        println!("Other:");
        println!("  status                - Show connection status");
        println!("  history               - Show command history");
        println!("  clear                 - Clear screen");
        println!("  help/?                - Show this help");
        println!();
    }

    async fn handle_pwd(&mut self) -> Result<()> {
        match self.client.pwd().await {
            Ok(path) => {
                self.current_directory = path.clone();
                println!("📁 Current directory: {}", path);
            }
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    async fn handle_list(&mut self, args: &[&str]) -> Result<()> {
        let path = args.get(0).map(|s| *s);
        match self.client.list(path).await {
            Ok(entries) => {
                println!("📋 Directory listing:");
                for entry in entries {
                    println!("  {}", entry);
                }
            }
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    async fn handle_cd(&mut self, args: &[&str]) -> Result<()> {
        if let Some(path) = args.get(0) {
            match self.client.cwd(path).await {
                Ok(_) => {
                    self.current_directory = path.to_string();
                    println!("📁 Changed to directory: {}", path);
                }
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: cd <path>");
        }
        Ok(())
    }

    async fn handle_mkdir(&mut self, args: &[&str]) -> Result<()> {
        if let Some(path) = args.get(0) {
            match self.client.mkdir(path).await {
                Ok(_) => println!("📁 Created directory: {}", path),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: mkdir <path>");
        }
        Ok(())
    }

    async fn handle_rmdir(&mut self, args: &[&str]) -> Result<()> {
        if let Some(path) = args.get(0) {
            match self.client.rmdir(path).await {
                Ok(_) => println!("🗑️ Removed directory: {}", path),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: rmdir <path>");
        }
        Ok(())
    }

    async fn handle_delete(&mut self, args: &[&str]) -> Result<()> {
        if let Some(file) = args.get(0) {
            match self.client.delete(file).await {
                Ok(_) => println!("🗑️ Deleted file: {}", file),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: delete <file>");
        }
        Ok(())
    }

    async fn handle_download(&mut self, args: &[&str]) -> Result<()> {
        if let Some(remote_file) = args.get(0) {
            let local_file = args.get(1).map(|s| *s).unwrap_or(remote_file);
            
            println!("⬇️ Downloading {} to {}...", remote_file, local_file);
            
            match self.client.download_file(remote_file, std::path::Path::new(local_file)).await {
                Ok(result) => {
                    println!("✅ Download completed!");
                    println!("  Bytes: {}", result.bytes_transferred);
                    println!("  Duration: {:.2}s", result.duration.as_secs_f64());
                    println!("  Speed: {:.2} KB/s", result.speed / 1024.0);
                }
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: get <remote_file> [local_file]");
        }
        Ok(())
    }

    async fn handle_upload(&mut self, args: &[&str]) -> Result<()> {
        if let Some(local_file) = args.get(0) {
            let remote_file = args.get(1).map(|s| *s).unwrap_or(local_file);
            
            println!("⬆️ Uploading {} to {}...", local_file, remote_file);
            
            match self.client.upload_file(std::path::Path::new(local_file), remote_file).await {
                Ok(result) => {
                    println!("✅ Upload completed!");
                    println!("  Bytes: {}", result.bytes_transferred);
                    println!("  Duration: {:.2}s", result.duration.as_secs_f64());
                    println!("  Speed: {:.2} KB/s", result.speed / 1024.0);
                }
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: put <local_file> [remote_file]");
        }
        Ok(())
    }

    async fn handle_pasv(&mut self) -> Result<()> {
        match self.client.set_transfer_mode(shared::types::TransferMode::Passive).await {
            Ok(_) => println!("🔒 Set to passive mode"),
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    async fn handle_port(&mut self, args: &[&str]) -> Result<()> {
        if let Some(port_str) = args.get(0) {
            if let Ok(port) = port_str.parse::<u16>() {
                match self.client.set_data_port(port).await {
                    Ok(_) => println!("🔓 Set active mode port: {}", port),
                    Err(e) => println!("❌ Error: {}", e),
                }
            } else {
                println!("❌ Invalid port number: {}", port_str);
            }
        } else {
            println!("❌ Usage: port <port_number>");
        }
        Ok(())
    }

    async fn handle_type(&mut self, args: &[&str]) -> Result<()> {
        if let Some(transfer_type) = args.get(0) {
            match self.client.set_transfer_type(transfer_type).await {
                Ok(_) => println!("📝 Set transfer type to: {}", transfer_type),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: type <A|I>");
        }
        Ok(())
    }

    async fn handle_binary(&mut self) -> Result<()> {
        match self.client.set_transfer_type("I").await {
            Ok(_) => println!("📝 Set to binary transfer"),
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    async fn handle_ascii(&mut self) -> Result<()> {
        match self.client.set_transfer_type("A").await {
            Ok(_) => println!("📝 Set to ASCII transfer"),
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    async fn handle_rest(&mut self, args: &[&str]) -> Result<()> {
        if let Some(offset_str) = args.get(0) {
            if let Ok(offset) = offset_str.parse::<u64>() {
                match self.client.set_resume_offset(offset).await {
                    Ok(_) => println!("⏩ Set resume offset: {} bytes", offset),
                    Err(e) => println!("❌ Error: {}", e),
                }
            } else {
                println!("❌ Invalid offset: {}", offset_str);
            }
        } else {
            println!("❌ Usage: rest <offset>");
        }
        Ok(())
    }

    async fn handle_size(&mut self, args: &[&str]) -> Result<()> {
        if let Some(file) = args.get(0) {
            match self.client.size(file).await {
                Ok(size) => println!("📏 File size: {} bytes", size),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: size <file>");
        }
        Ok(())
    }

    async fn handle_mdtm(&mut self, args: &[&str]) -> Result<()> {
        if let Some(file) = args.get(0) {
            match self.client.mdtm(file).await {
                Ok(time) => println!("🕒 File modification time: {}", time),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: mdtm <file>");
        }
        Ok(())
    }

    async fn handle_status(&mut self) -> Result<()> {
        println!("📊 Connection Status:");
        println!("====================");
        println!("Current directory: {}", self.current_directory);
        println!("Connected: {}", if self.client.is_connected() { "✅ Yes" } else { "❌ No" });
        println!("Authenticated: {}", if self.client.is_authenticated() { "✅ Yes" } else { "❌ No" });
        Ok(())
    }

    async fn handle_connect(&mut self, args: &[&str]) -> Result<()> {
        if let Some(host) = args.get(0) {
            let port = args.get(1)
                .and_then(|s| s.parse::<u16>().ok())
                .unwrap_or(21);
            
            println!("🔌 Connecting to {}:{}...", host, port);
            
            match self.client.connect(host, port).await {
                Ok(_) => println!("✅ Connected to {}:{}", host, port),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: connect <host> [port]");
        }
        Ok(())
    }

    async fn handle_login(&mut self, args: &[&str]) -> Result<()> {
        if let (Some(username), Some(password)) = (args.get(0), args.get(1)) {
            println!("🔐 Logging in as {}...", username);
            
            match self.client.login(username, password).await {
                Ok(_) => println!("✅ Logged in successfully"),
                Err(e) => println!("❌ Error: {}", e),
            }
        } else {
            println!("❌ Usage: login <username> <password>");
        }
        Ok(())
    }

    async fn handle_disconnect(&mut self) -> Result<()> {
        println!("🔌 Disconnecting...");
        match self.client.quit().await {
            Ok(_) => println!("✅ Disconnected"),
            Err(e) => println!("❌ Error: {}", e),
        }
        Ok(())
    }

    fn show_history(&self) {
        println!("📜 Command History:");
        println!("==================");
        for (i, cmd) in self.command_history.iter().enumerate() {
            println!("{:3}: {}", i + 1, cmd.trim());
        }
    }

    fn clear_screen(&self) {
        print!("\x1B[2J\x1B[1;1H");
        io::stdout().flush().unwrap();
    }
}
